﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

namespace ToddMcDermid.SSIS
{
    #region CLASS: DtsDataTypes
    public class DtsDataTypes
    {
        #region STRUCT: DataTypeDescriptionStruct
        public struct DataTypeDescriptionStruct : IComparable
        {
            #region Private Variables
            private readonly DataType _dataType;
            private readonly string _technicalName;
            private readonly string _generalName;
            private readonly bool _hasLength;
            private readonly bool _hasCodePage;
            private readonly bool _hasPrecision;
            private readonly bool _hasScale;
            #endregion

            #region Constructor
            public DataTypeDescriptionStruct(DataType dataType, string technicalName, string generalName,
                bool hasLength, bool hasCodePage, bool hasPrecision, bool hasScale)
            {
                this._dataType = dataType;
                this._technicalName = technicalName;
                this._generalName = generalName;
                this._hasLength = hasLength;
                this._hasCodePage = hasCodePage;
                this._hasPrecision = hasPrecision;
                this._hasScale = hasScale;
            }
            #endregion

            #region Public Properties
            public DataType DataType
            {
                get { return this._dataType; }
            }

            public string TechnicalName
            {
                get { return this._technicalName; }
            }

            public string GeneralName
            {
                get { return this._generalName; }
            }

            public string CompleteName
            {
                get { return this._generalName + " [" + this._technicalName + "]"; }
            }

            public bool HasLength
            {
                get { return this._hasLength; }
            }

            public bool HasCodePage
            {
                get { return this._hasCodePage; }
            }
            
            public bool HasPrecision
            {
                get { return this._hasPrecision; }
            }

            public bool HasScale
            {
                get { return this._hasScale; }
            }
            #endregion

            #region IComparable Members
            public int CompareTo(object obj)
            {
                DataTypeDescriptionStruct otherStruct = (DataTypeDescriptionStruct)obj;

                return this._generalName.CompareTo(otherStruct._generalName);
            }
            #endregion
        }
        #endregion

        #region Static Variables
        private static readonly DataTypeDescriptionStruct __empty;
        public static readonly DataTypeDescriptionStruct[] DataTypeDescriptions;
        #endregion

        #region Static Constructor
        static DtsDataTypes()
        {
            DtsDataTypes.__empty = new DataTypeDescriptionStruct(DataType.DT_EMPTY, "Empty", "Empty", false, false, false, false);
            Microsoft.SqlServer.Dts.Runtime.Application dtsApplication = new Microsoft.SqlServer.Dts.Runtime.Application();
            DtsDataTypes.DataTypeDescriptions = new DataTypeDescriptionStruct[dtsApplication.DataTypeInfos.Count];
            for (int index = 0; index < dtsApplication.DataTypeInfos.Count; index++)
            {
                DataType dataType = (DataType)Enum.Parse(typeof(DataType), dtsApplication.DataTypeInfos[index].TypeEnumName);

                DtsDataTypes.DataTypeDescriptions[index] = new DataTypeDescriptionStruct(dataType,
                    dtsApplication.DataTypeInfos[index].TypeEnumName, dtsApplication.DataTypeInfos[index].TypeName,
                    (dataType == DataType.DT_STR) || (dataType == DataType.DT_WSTR) || (dataType == DataType.DT_BYTES),
                    (dataType == DataType.DT_STR) || (dataType == DataType.DT_TEXT),
                    (dataType == DataType.DT_NUMERIC),
                    (dataType == DataType.DT_NUMERIC) || (dataType == DataType.DT_DECIMAL) || (dataType == DataType.DT_DBTIME2) || (dataType == DataType.DT_DBTIMESTAMP2) || (dataType == DataType.DT_DBTIMESTAMPOFFSET));
            }
            Array.Sort(DtsDataTypes.DataTypeDescriptions);
        }
        #endregion

        #region Static Methods
        public static DataTypeDescriptionStruct GetDataTypeDescriptionStruct(DataType dataType)
        {
            DataTypeDescriptionStruct dataTypeDescriptionStruct = DtsDataTypes.__empty;

            for (int index = 0; index < DtsDataTypes.DataTypeDescriptions.Length; index++)
            {
                if (dataType == DtsDataTypes.DataTypeDescriptions[index].DataType)
                {
                    dataTypeDescriptionStruct = DtsDataTypes.DataTypeDescriptions[index];
                    break;
                }
            }

            return dataTypeDescriptionStruct;
        }

        public static string SpecificDataTypeTechnicalDescription(DataType dataType, int length, int codePage, int precision, int scale)
        {
            switch (dataType)
            {
                case DataType.DT_DECIMAL:
                case DataType.DT_DBTIME2:
                case DataType.DT_DBTIMESTAMP2:
                case DataType.DT_DBTIMESTAMPOFFSET:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ", " + scale.ToString() + ")";

                case DataType.DT_NUMERIC:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ", " + precision.ToString() + ", " + scale.ToString() + ")";

                case DataType.DT_STR:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ", " + length.ToString() + ", " + codePage.ToString() + ")";

                case DataType.DT_BYTES:
                case DataType.DT_WSTR:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ", " + length.ToString() + ")";

                case DataType.DT_TEXT:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ", " + codePage.ToString() + ")";

                default:
                    return "(" + DtsDataTypes.GetDataTypeDescriptionStruct(dataType).TechnicalName + ")";
            }
        }
        #endregion
    }
    #endregion
}
